#ifndef TRACE_H
#define TRACE_H
#include "stdio.h"

#define TRACE_FUNCTION printf

#define DEBUG_FUNCTION printf

#define ASSERT_FUNCTION printf

/* ASSERT configuration */
#define ASSERT_EN
//#undef ASSERT_EN
/* END of assert configuration */

/* DEBUG configuration. Please modify only here!!! */
#define DEBUG
//#undef DEBUG
/* END of debug configuration */

/* TRACE configuration. Please modify only here!!! */
//#define DISABLE_TRACE_MAIN
//#define DISABLE_TRACE_INFO
//#define DISABLE_TRACE_WARNING
//#define DISABLE_TRACE_ERROR
#define APP_TRACE
//#undef APP_TRACE
/* END of trace configuration */

/* TRACE internal parameters */
#define APP_TRACE_MASK_NONE		0
#define APP_TRACE_MASK_MAIN		1
#define APP_TRACE_MASK_INFO		2
#define APP_TRACE_MASK_WARN		4
#define APP_TRACE_MASK_ERROR	8

#ifdef DISABLE_TRACE_MAIN
#undef 	  	APP_TRACE_MASK_MAIN
#define	APP_TRACE_MASK_MAIN 0
#endif

#ifdef DISABLE_TRACE_INFO
#undef 	  	APP_TRACE_MASK_INFO
#define	APP_TRACE_MASK_INFO 0
#endif

#ifdef DISABLE_TRACE_WARNING
#undef 	  	APP_TRACE_MASK_WARN
#define	APP_TRACE_MASK_WARN 0
#endif

#ifdef DISABLE_TRACE_ERROR
#undef 	  	APP_TRACE_MASK_ERROR
#define	APP_TRACE_MASK_ERROR 0
#endif

#define APP_TRACE_LEVEL (APP_TRACE_MASK_MAIN | \
                         APP_TRACE_MASK_INFO | \
						 APP_TRACE_MASK_WARN | \
						 APP_TRACE_MASK_ERROR)

/* definitions section */
#ifdef APP_TRACE
	#define TRACE(x, ...) \
		do { if (APP_TRACE_LEVEL & x) TRACE_FUNCTION(__VA_ARGS__); \
             else ; \
           } while(0)
#else
	#define TRACE(x, ...)
#endif

#define TRACE_MAIN(...) \
    do { \
        TRACE(APP_TRACE_MASK_MAIN, "[%s_MAIN]->", __FUNCTION__); \
        TRACE(APP_TRACE_MASK_MAIN, __VA_ARGS__); \
        TRACE(APP_TRACE_MASK_MAIN, "|:%d\r\n", __LINE__); \
    }while(0)

#define TRACE_INFO(...) \
    do { \
        TRACE(APP_TRACE_MASK_INFO, "[%s_INFO]->", __FUNCTION__); \
        TRACE(APP_TRACE_MASK_INFO, __VA_ARGS__); \
        TRACE(APP_TRACE_MASK_INFO, "|:%d\r\n", __LINE__); \
    }while(0)

#define TRACE_WARN(...) \
    do { \
        TRACE(APP_TRACE_MASK_WARN, "[%s_WARN]->", __FUNCTION__); \
        TRACE(APP_TRACE_MASK_WARN, __VA_ARGS__); \
        TRACE(APP_TRACE_MASK_WARN, "|:%d\r\n", __LINE__); \
    }while(0)

#define TRACE_ERROR(...) \
    do { \
        TRACE(APP_TRACE_MASK_ERROR, "[%s_ERR]->", __FUNCTION__); \
        TRACE(APP_TRACE_MASK_ERROR, __VA_ARGS__); \
        TRACE(APP_TRACE_MASK_ERROR, "|:%d\r\n", __LINE__); \
    }while(0)

#define TRACE_USER(...) \
	do { \
		TRACE((APP_TRACE_MASK_ERROR | APP_TRACE_MASK_WARN | APP_TRACE_MASK_INFO | APP_TRACE_MASK_MAIN), __VA_ARGS__); \
	}while(0)

#ifdef DEBUG

#define DBG(...) \
    do { \
        DEBUG_FUNCTION("[%s_DBG]->", __FUNCTION__); \
        DEBUG_FUNCTION(__VA_ARGS__); \
        DEBUG_FUNCTION("|:%d\r\n", __LINE__); \
    }while(0)

#else
    DBG(...)
#endif


#ifdef ASSERT_EN

#define ASSERT(exp)  if (exp) ; \
        else \
            do{ \
                ASSERT_FUNCTION("Assert(%s) failed in %s:%d\r\n",#exp, __FUNCTION__,__LINE__); \
                return ERR; \
            }while(0)

#define ASSERT_ZERO(structure) { \
			char* ppppp  = (char*)&structure; \
			int   iiiiii = 0; \
			for (iiiiii = 0; iiiiii < sizeof(structure); iiiiii++) { \
				ASSERT(*ppppp == 0); \
				ppppp++; \
			} \
		}

#else

#define ASSERT(exp)

#define ASSERT_ZERO(structure){}

#endif

#endif
/* End of file */

